using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using TenantManagementService.Monitoring;

namespace TenantManagementService.Monitoring
{
    /// <summary>
    /// Prometheus 指标收集服务
    /// </summary>
    public class PrometheusMetricsService : ITransientDependency
    {
        private readonly ILogger<PrometheusMetricsService> _logger;

        // Prometheus 指标存储（实际项目中应使用 Prometheus.Client 库）
        private readonly Dictionary<string, PrometheusMetric> _metrics = new();

        public PrometheusMetricsService(ILogger<PrometheusMetricsService> logger)
        {
            _logger = logger;
            InitializeDefaultMetrics();
        }

        /// <summary>
        /// 记录 Counter 指标
        /// </summary>
        public void RecordCounter(string metricName, double value = 1, Dictionary<string, string>? labels = null)
        {
            try
            {
                var key = GetMetricKey(metricName, labels);

                if (!_metrics.ContainsKey(key))
                {
                    _metrics[key] = new PrometheusMetric
                    {
                        Name = metricName,
                        Type = PrometheusMetricType.Counter,
                        Labels = labels ?? new Dictionary<string, string>(),
                        Value = 0
                    };
                }

                _metrics[key].Value += value;
                _metrics[key].LastUpdated = DateTime.Now;

                _logger.LogDebug("记录 Counter 指标: {MetricName} = {Value}", metricName, _metrics[key].Value);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录 Counter 指标失败: {MetricName}", metricName);
            }
        }

        /// <summary>
        /// 记录 Gauge 指标
        /// </summary>
        public void RecordGauge(string metricName, double value, Dictionary<string, string>? labels = null)
        {
            try
            {
                var key = GetMetricKey(metricName, labels);

                if (!_metrics.ContainsKey(key))
                {
                    _metrics[key] = new PrometheusMetric
                    {
                        Name = metricName,
                        Type = PrometheusMetricType.Gauge,
                        Labels = labels ?? new Dictionary<string, string>(),
                        Value = value
                    };
                }
                else
                {
                    _metrics[key].Value = value;
                }

                _metrics[key].LastUpdated = DateTime.Now;

                _logger.LogDebug("记录 Gauge 指标: {MetricName} = {Value}", metricName, value);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录 Gauge 指标失败: {MetricName}", metricName);
            }
        }

        /// <summary>
        /// 记录 Histogram 指标
        /// </summary>
        public void RecordHistogram(string metricName, double value, Dictionary<string, string>? labels = null, double[]? buckets = null)
        {
            try
            {
                var key = GetMetricKey(metricName, labels);

                if (!_metrics.ContainsKey(key))
                {
                    _metrics[key] = new PrometheusMetric
                    {
                        Name = metricName,
                        Type = PrometheusMetricType.Histogram,
                        Labels = labels ?? new Dictionary<string, string>(),
                        Buckets = buckets ?? GetDefaultBuckets(),
                        HistogramValues = new List<double>(),
                        Value = 0
                    };
                }

                var metric = _metrics[key];
                metric.HistogramValues?.Add(value);
                metric.Value++; // 增加观测次数
                metric.LastUpdated = DateTime.Now;

                _logger.LogDebug("记录 Histogram 指标: {MetricName} = {Value}", metricName, value);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录 Histogram 指标失败: {MetricName}", metricName);
            }
        }

        /// <summary>
        /// 记录 Summary 指标
        /// </summary>
        public void RecordSummary(string metricName, double value, Dictionary<string, string>? labels = null)
        {
            try
            {
                var key = GetMetricKey(metricName, labels);

                if (!_metrics.ContainsKey(key))
                {
                    _metrics[key] = new PrometheusMetric
                    {
                        Name = metricName,
                        Type = PrometheusMetricType.Summary,
                        Labels = labels ?? new Dictionary<string, string>(),
                        SummaryValues = new List<double>(),
                        Value = value
                    };
                }
                else
                {
                    var metric = _metrics[key];
                    metric.SummaryValues?.Add(value);

                    // 计算平均值
                    if (metric.SummaryValues != null && metric.SummaryValues.Count > 0)
                    {
                        metric.Value = metric.SummaryValues.Average();
                    }
                }

                _metrics[key].LastUpdated = DateTime.Now;

                _logger.LogDebug("记录 Summary 指标: {MetricName} = {Value}", metricName, value);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录 Summary 指标失败: {MetricName}", metricName);
            }
        }

        /// <summary>
        /// 增加指标
        /// </summary>
        public void Increment(string metricName, Dictionary<string, string>? labels = null)
        {
            RecordCounter(metricName, 1, labels);
        }

        /// <summary>
        /// 减少指标
        /// </summary>
        public void Decrement(string metricName, Dictionary<string, string>? labels = null)
        {
            RecordCounter(metricName, -1, labels);
        }

        /// <summary>
        /// 获取指标值
        /// </summary>
        public double? GetMetricValue(string metricName, Dictionary<string, string>? labels = null)
        {
            var key = GetMetricKey(metricName, labels);
            return _metrics.ContainsKey(key) ? _metrics[key].Value : null;
        }

        /// <summary>
        /// 获取所有指标
        /// </summary>
        public Dictionary<string, PrometheusMetric> GetAllMetrics()
        {
            return new Dictionary<string, PrometheusMetric>(_metrics);
        }

        /// <summary>
        /// 重置指标
        /// </summary>
        public void ResetMetric(string metricName, Dictionary<string, string>? labels = null)
        {
            var key = GetMetricKey(metricName, labels);
            if (_metrics.ContainsKey(key))
            {
                var metric = _metrics[key];
                metric.Value = metric.Type == PrometheusMetricType.Counter ? 0 : metric.Value;
                metric.HistogramValues?.Clear();
                metric.SummaryValues?.Clear();
                metric.LastUpdated = DateTime.Now;
            }
        }

        /// <summary>
        /// 清空所有指标
        /// </summary>
        public void ClearAllMetrics()
        {
            _metrics.Clear();
            InitializeDefaultMetrics();
        }

        /// <summary>
        /// 生成 Prometheus 格式的指标文本
        /// </summary>
        public string GeneratePrometheusMetricsText()
        {
            var lines = new List<string>();

            foreach (var metricGroup in _metrics.Values.GroupBy(m => m.Name))
            {
                var metricName = metricGroup.Key;
                var baseMetric = metricGroup.First();

                // 添加指标类型和帮助信息
                lines.Add($"# HELP {metricName} {GetMetricHelp(metricName)}");
                lines.Add($"# TYPE {metricName} {GetPrometheusType(baseMetric.Type)}");

                // 添加指标值
                foreach (var metric in metricGroup)
                {
                    var labelString = metric.Labels.Any() ?
                        $"{{{string.Join(",", metric.Labels.Select(kv => $"{kv.Key}=\"{kv.Value}\""))}}}" : "";

                    lines.Add($"{metricName}{labelString} {metric.Value:0.######}");
                }

                lines.Add(""); // 空行分隔
            }

            return string.Join("\n", lines);
        }

        /// <summary>
        /// 获取指标统计信息
        /// </summary>
        public PrometheusMetricsStatistics GetStatistics()
        {
            return new PrometheusMetricsStatistics
            {
                TotalMetrics = _metrics.Count,
                Counters = _metrics.Values.Count(m => m.Type == PrometheusMetricType.Counter),
                Gauges = _metrics.Values.Count(m => m.Type == PrometheusMetricType.Gauge),
                Histograms = _metrics.Values.Count(m => m.Type == PrometheusMetricType.Histogram),
                Summaries = _metrics.Values.Count(m => m.Type == PrometheusMetricType.Summary),
                LastUpdated = _metrics.Values.Any() ? _metrics.Values.Max(m => m.LastUpdated) : DateTime.MinValue
            };
        }

        private void InitializeDefaultMetrics()
        {
            // 初始化一些默认指标
            RecordGauge("tenant_management_service_uptime", 0);
            RecordGauge("tenant_management_service_memory_usage", 0);
            RecordCounter("tenant_management_service_requests_total", 0);
            RecordCounter("tenant_management_service_errors_total", 0);
            RecordHistogram("tenant_management_service_request_duration_seconds", 0);
        }

        private string GetMetricKey(string metricName, Dictionary<string, string>? labels)
        {
            if (labels == null || !labels.Any())
            {
                return metricName;
            }

            var sortedLabels = labels.OrderBy(kv => kv.Key);
            var labelString = string.Join(",", sortedLabels.Select(kv => $"{kv.Key}={kv.Value}"));
            return $"{metricName}[{labelString}]";
        }

        private string GetMetricHelp(string metricName)
        {
            return metricName switch
            {
                "tenant_management_service_uptime" => "Service uptime in seconds",
                "tenant_management_service_memory_usage" => "Memory usage in bytes",
                "tenant_management_service_requests_total" => "Total number of requests",
                "tenant_management_service_errors_total" => "Total number of errors",
                "tenant_management_service_request_duration_seconds" => "Request duration in seconds",
                _ => "Auto-generated metric"
            };
        }

        private string GetPrometheusType(PrometheusMetricType type)
        {
            return type switch
            {
                PrometheusMetricType.Counter => "counter",
                PrometheusMetricType.Gauge => "gauge",
                PrometheusMetricType.Histogram => "histogram",
                PrometheusMetricType.Summary => "summary",
                _ => "untyped"
            };
        }

        private double[] GetDefaultBuckets()
        {
            return new[] { 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10 };
        }
    }

    /// <summary>
    /// Prometheus 指标
    /// </summary>
    public class PrometheusMetric
    {
        public string Name { get; set; } = string.Empty;
        public PrometheusMetricType Type { get; set; }
        public Dictionary<string, string> Labels { get; set; } = new();
        public double Value { get; set; }
        public double[]? Buckets { get; set; }
        public List<double>? HistogramValues { get; set; }
        public List<double>? SummaryValues { get; set; }
        public DateTime LastUpdated { get; set; }
    }

    /// <summary>
    /// Prometheus 指标类型
    /// </summary>
    public enum PrometheusMetricType
    {
        Counter,
        Gauge,
        Histogram,
        Summary
    }

    /// <summary>
    /// Prometheus 指标统计
    /// </summary>
    public class PrometheusMetricsStatistics
    {
        public int TotalMetrics { get; set; }
        public int Counters { get; set; }
        public int Gauges { get; set; }
        public int Histograms { get; set; }
        public int Summaries { get; set; }
        public DateTime LastUpdated { get; set; }
    }
}